8822B narrowband: fix RF18 re-latch edge (full 5/10 MHz on both Jaguar2 variants) + kernel-parity ports#219
Merged
Merged
Conversation
…gap narrowed to unreadable state Systematic devourer-vs-kernel comparison on the 8822BU (per the incomplete-port pattern of issue #184), driven by hardware A/B against the vendored OpenHD module (patched rebuilds + write_reg flips): - Port halmac send_general_info: the GENERAL_INFO + PHYDM_INFO H2C pair (32-byte h2c packets over the H2C queue, qsel 0x13, wire format byte-verified via usbmon) sent after DLFW — the only H2C traffic the kernel driver produces. Hands the FW its rfe/rf-type/cut/antenna/ package identity; groundwork for FW-side features even though the NB arming theory it came from was FALSIFIED (a kernel build with the pair patched out keeps full-rate NB). - Port halmac cfg_mac_clk: MAC clock select 80 MHz + TSF/EDCA microsecond-tick dividers (0x55c/0x638 = 80). The chip reset defaults are wrong for the running clock (0x64/0x28 read back); the kernel rewrites them on every bandwidth config, devourer never did. - Enable SoML (adaptive ML detection, 0x19a8 = 0xd90a0000 — the kernel's steady 8822B state; devourer sat in the SoML-off world the vendor uses only for specific RFE types) + the config_phydm_switch_band RxHP companion block (0x8cc/0x8d8/0xc04/0xe04 by band and RFE). Measured: 8822B 20 MHz RX ~2x better (8200 vs ~4700 hits per cell); 8821C narrowband at its best reading yet (10000 hits). 20/40/80 smokes and ctest pass on both variants. 8822B narrowband itself remains gated: the elimination now proves the kernel keeps full-rate NB with devourer's ENTIRE differing readable register state (116-register MAC+BB flip + RF filter values), so the causal delta is unreadable state (gain LUTs behind write-only ports / sequencing latches). Next experiment documented in the NB branch comment: golden-init replay of the kernel's captured post-DLFW write sequence. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Found by diffing the kernel driver's complete init write sequence (usbmon pcap, 7836 vendor writes) against devourer's own write log (DEVOURER_LOG_WRITES) — the systematic source-level comparison: - halrf kfree port: kfree_init reads the PPG physical-efuse trims (2G/5G per-band-group TX gain 0x3DB..0x3EE, 2G PA bias 0x3D5/0x3D6) and applies the PA-bias RF LUT correction — the RF 0x51/0x52 word recomposed and written into RF LUT entries 0/1/3 through the 0xef[10] window (write-only LUT state; this is the 0x3f=0x4bb block in the kernel's golden init that devourer never produced). kfree_apply programs the per-channel-group TX gain trim (RF 0xde/0x65/0x55) on every full channel set, phydm_config_kfree parity. Gotcha ported with it: RF LUT windows left open by the table apply alias the 0x51/0x52 reads — close 0xef before reading. - CCA threshold table: RFE types 3/5/12/15/16/17/19 (external-FEM boards — including the bench T3U, rfe_type 3) must use the cca_ifem_ccut_rfe table (0x82c=0x75da8010, distinct 0x830/0x838 columns); devourer hardcoded the plain iFEM C-cut column for every board, leaving eFEM boards with mis-set carrier-sense thresholds. Plus the vendor's 20 MHz DFS-channel CCA adjust (0x838[7:4]=5 for ch52-144). Regression: 20/40/80 smokes + ctest pass on both variants; 8822B 20 MHz on-air RX holds at the improved level (8100 hits/cell). 8822B narrowband remains gated — these close real parity gaps but the NB sync deficit persists; the remaining un-ported channel-set component is the phydm spur-calibration/PSD machinery, and the composite golden-init replay stays the definitive next experiment (see the NB branch comment). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… notch) The last un-ported component of the vendor's channel-set tail (phydm_spur_calibration_8822b -> phydm_dynamic_spur_det_eliminate, enabled by CONFIG_8822B_SPUR_CALIBRATION in the CE build): - Reset half on every channel set: clear the CSI mask bank (0x880..0x89c, 0x874[0]) and both NBI notch enables (0x87c[13], 0xc20[28]/0xe20[28]) — vendor parity for the mask-clear writes the kernel produces on every switch. - Detection half on the chip's own spur channels (2G 5-8/13 @20M, 3-11 @40m; 5G 153/161/54/118/151/159/58/122/155): PSD-scan the spur frequency point +/-1 (3-wire off, per-path 0x808 select, PSD engine 0x910 BIT(22)|freq_pt, report 0xf44[15:0], IGI toggle to re-enter RX), and above the vendor threshold (0x8D) program the NBI notch + CSI mask at the spur frequency (2440/2480/5280/5600/5760/5800 MHz per channel/BW) through the existing ToneMask appliers, plus the dsde CCA tweak (0x82c[19:12]). Hardware-validated on the T3U at ch6 (a real spur channel): the scan measures PSD A=634/B=515 >= threshold and engages the notch at 2440 MHz; 20 MHz RX healthy with the notch active (7400 hits/cell); non-spur ch44 rides the reset-only path (7200 hits/cell); smokes + ctest pass on both variants. Narrowband bw 5/6 takes the reset-only path (matches the vendor, whose dsde tables only key 20/40/80) — the 8822B NB sync deficit is unchanged and remains gated; also measured this session: the deficit is band-independent (2.4 GHz ch6 NB reads the same ~10 sync as 5 GHz). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… + golden-init replay lever Root cause of the 8822B 5/10 MHz deadness, isolated by golden-init replay: capture the working kernel driver's complete post-DLFW register write stream from usbmon (3630 writes), replay it verbatim from devourer (new DEVOURER_REPLAY_WSEQ debug knob — applied at the end of Init, overriding devourer's own config), confirm NB unlocks (39100 hits vs ~10), then delta-debug the stream down to a single causal write pair: RF 0x18 = <different channel byte> RF 0x18 = <real value> The 8822B RF synthesizer only re-latches its internal channel state on an RF18 VALUE EDGE — a same-value rewrite does nothing. The kernel never hits this because its flow always tunes through a channel/band change around a bandwidth switch; devourer's end-of-bring-up narrowband re-clock rewrote RF18 with the identical value, leaving the RF latched to pre-re-clock internals (RX deaf, TX invalid, band-independent). Verified minimally: the edge pair alone recovers 23300 hits; the same-value rewrite alone stays at 9. Fix: in the 8822B narrowband path, write RF18 once with a substitute channel byte before the real value (both RF paths). Hardware validation (T3U 8822BU x Jaguar3 8812CU, true frame counts): - ch44 10M RX 7700, TX 12600; ch44 5M RX 6500; 2.4G ch6 10M RX 7700 - scripted cross-RX: 20M=3900 / 10M=4000 / 5M=3900 — full control parity - 20/40/80 smokes + ctest pass; the edge is NB-gated (wide paths untouched) Caps ungated: narrowband_ok=true on both Jaguar2 variants, bw_mask keeps kBw5|kBw10. Docs/tests updated to current state; DEVOURER_REPLAY_WSEQ kept as a permanent debugging lever (the tool that found this). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
PR #216 shipped Jaguar2 5/10 MHz narrowband but gated the 8822B — it synced ~0.5% of NB frames on RX and aired nothing on TX, while the OpenHD kernel module did full-rate NB on the same dongle with the same firmware. This PR finds and fixes the root cause, and lands the vendor-parity gaps discovered along the way.
Root cause: RF18 re-latch edge
The RTL8822B RF synthesizer only re-latches its internal channel state on an RF18 (
RF 0x18) value edge — a same-value rewrite is a no-op. Devourer applies narrowband as an end-of-bring-up re-clock and rewrote RF18 with the identical value, leaving the RF latched to its pre-re-clock internals: RX deaf, TX invalid, band-independent. The kernel driver never exposes this because its flow always tunes through a channel/band change (an RF18 edge) around any bandwidth switch.This also retroactively explains the earlier "firmware-autonomous RF
0x82/0xf2retune" observation — those are RF-internal LUT outputs refreshed by the RF18 edge, not FW action.Fix (
set_channel_bw, 8822B NB branch): write RF18 once with a substitute channel byte, then the real value, on both RF paths.How it was found — golden-init replay
Every readable-state hypothesis had already been eliminated by A/B against the vendored kernel module (a 116-register MAC+BB flip and removal of the module's only H2C traffic both left kernel NB working). The latch is invisible to state diffing because it keys on the write event, not the value. So:
DEVOURER_REPLAY_WSEQdebug knob (applied at end ofInit, overriding devourer's own config) → NB unlocks (39100 hits vs ~10) → causal state is host-writable.DEVOURER_REPLAY_WSEQis kept as a permanent lever — it converts any "same registers, different behavior" mystery into a mechanical bisection.Hardware validation (T3U 8822BU ↔ Jaguar3 8812CU, true frame counts)
tests/narrowband_cross_rx.sh: 20M=3900 / 10M=4000 / 5M=3900 — full control parity, both widthsctestpass; the RF18 edge is narrowband-gated (wide paths byte-unchanged)Caps ungated:
narrowband_ok=trueon both Jaguar2 variants,bw_maskkeeps 5/10.Also in this branch (kernel-parity ports found by the same comparison)
These were prerequisites/gap-closures uncovered while diffing devourer's init against the kernel's write stream. Each is independently vendor-parity and measured; together they roughly doubled 8822B 20 MHz RX (~4700 → ~8100 hits/cell) before the NB fix:
0x51/0x52→0x3fvia the0xef[10]window) + per-channel-group TX gain trim (RF 0xde/0x65/0x55). Gotcha ported with it: close the RF LUT window before the0x51/0x52reads (the table apply leaves it open, aliasing the reads).cca_ifem_ccut_rfe; devourer hardcoded the plain iFEM column for every board. Plus the 20 MHz DFS-channel CCA adjust.0x55c/0x638); chip reset defaults are wrong for the running clock.send_fw_general_info) — the kernel's post-DLFW FW identity handshake.Test notes
DEVOURER_REPLAY_WSEQ=<file>— golden-init replay (lines:<addr_hex> <width 1|2|4> <val_hex>).tests/narrowband_cross_rx.sh/tests/jaguar2_narrowband_sdr.shnow cover both Jaguar2 variants.🤖 Generated with Claude Code